package java_thinking.unit_21._21_2;

import net.jcip.annotations.NotThreadSafe;

import javax.servlet.GenericServlet;
import javax.servlet.Servlet;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.math.BigInteger;
import java.util.concurrent.atomic.AtomicReference;

/**
 * @Desc:   2-5 没有足够原子性保证情况下对其最近计算结果进行缓存,任然存在竟态条件！ 不要这么做
 *          1.AtomicReference : 底层使用的是compareAndSwapObject实现CAS，比较的是两个对象的地址是否相等
 *                              也就是它可以保证你在修改对象引用时的线程安全性
 *
 *          2.当在不变性条件中设计多个变量时，各个变量之间并不是彼此独立的，而是某个变量的值会
 *            对其他变量的值产生约束，因此，当更新某个一变量时，需要在统一个原子操作中对其他变
 *            量同时进行更新
 *
 *          3.要保持状态的一致性，就需要在单个原子操作中更新所有相关的状态变量
 * @author: cww
 * @DateTime: 2019/5/29 20:38
 */
@NotThreadSafe
public class UnsafeCachingFactorize extends GenericServlet implements Servlet {
    private final AtomicReference<BigInteger> lastNumber = new AtomicReference<BigInteger>();
    private final AtomicReference<BigInteger[]> lastFactors = new AtomicReference<BigInteger[]>();

    @Override
    public void service(ServletRequest req, ServletResponse resp) {
        BigInteger i = extractFromRequest(req);
        if (i.equals(lastNumber.get()))
            encodeIntoResponse(resp, lastFactors.get());
        else {
            BigInteger[] factors = factor(i);
            lastNumber.set(i);
            lastFactors.set(factors);
            encodeIntoResponse(resp, factors);
        }
    }

    void encodeIntoResponse(ServletResponse resp, BigInteger[] factors) {
    }

    BigInteger extractFromRequest(ServletRequest req) {
        return new BigInteger("7");
    }

    BigInteger[] factor(BigInteger i) {
        // Doesn't really factor
        return new BigInteger[]{i};
    }
}
